#include "custom_stateful_action_node.h"

namespace task::node
{
class CustomStatefulActionNodeData
{
private:
    friend class CustomStatefulActionNode;
    std::shared_ptr<task::AbstractTask> task_;
    std::atomic<bool> start_res_{false};//任务开始结果，即是否开启成功
};
}

namespace task::node
{
CustomStatefulActionNode::CustomStatefulActionNode(const std::string &name, const BT::NodeConfiguration &config,
                                                   const std::shared_ptr<task::AbstractTask> &task)
    : StatefulActionNode(name, config), d(std::make_unique<CustomStatefulActionNodeData>())
{
    d->task_ = task;
}
CustomStatefulActionNode::~CustomStatefulActionNode() = default;

BT::NodeStatus CustomStatefulActionNode::onStart()
{
    d->start_res_.store(d->task_->onStart());
    return BT::NodeStatus::RUNNING;
}
BT::NodeStatus CustomStatefulActionNode::onRunning()
{
    if (!d->start_res_.load())
    {
        d->task_->onDone(false);
        return BT::NodeStatus::FAILURE;
    }
    if (d->task_->isTimeout() && !d->task_->onTimeout())
    {
        d->task_->onDone(false);
        return BT::NodeStatus::FAILURE;
    }
    TaskStatus taskStatus = d->task_->onRunning();
    switch (taskStatus)
    {
        case TaskStatus::Running:
            return BT::NodeStatus::RUNNING;
        case TaskStatus::Success:
            d->task_->stopTimeout();
            d->task_->onDone(true);
            return BT::NodeStatus::SUCCESS;
        case TaskStatus::Failure:
            d->task_->stopTimeout();
            d->task_->onDone(false);
            return BT::NodeStatus::FAILURE;
        default:
            EASE_ERROR("Unknown task status: %d", (int) taskStatus);
            break;
    }
    return BT::NodeStatus::IDLE;
}
void CustomStatefulActionNode::onHalted()
{
    d->task_->onHalt();
    d->task_->onDone(false);
}
bool CustomStatefulActionNode::onReactive()
{
    return d->task_->onReactive();
}
BT::NodeStatus CustomStatefulActionNode::onPause()
{
    return d->task_->onPause() ? BT::NodeStatus::SUCCESS : BT::NodeStatus::FAILURE;
}
BT::NodeStatus CustomStatefulActionNode::onResume()
{
    return d->task_->onResume() ? BT::NodeStatus::SUCCESS : BT::NodeStatus::FAILURE;
}
BT::NodeStatus CustomStatefulActionNode::onCancel()
{
    d->task_->onCancel();
    return BT::NodeStatus::RUNNING;
}
AbstractTask *CustomStatefulActionNode::getTask()
{
    return d->task_.get();
}
std::string CustomStatefulActionNode::toString(const std::string &prefix) const
{
    return prefix + type_utils::typeName(*this, {"task", "node"}) + ": " + name();
}
}
